home *** CD-ROM | disk | FTP | other *** search
- { This unit writes EAN-8 and EAN-13 barcodes to an Epson, IBM Pro or HP
- Laser compatible printers. It has been tested on a variety of printers
- and works well. The barcodes generated were able to be read by at least
- one brand of bar code reader.
-
- By Rohit Gupta
-
- You may use this as you see fit.
-
- }
-
- {$R-,B+,S-,I+,N-,D-,L-,Y-}
- {$M $4000,$4000,$8000}
-
- UNIT BarCode;
-
-
- INTERFACE
-
-
- CONST
- PrnPosn = 5; { Print Offset Column }
-
- TYPE
- EAN_13 = STRING [13];
-
- Printer_Type = (Epson, Ibm, Laser);
-
-
- PROCEDURE Print_BarCode
- (VAR Lst : TEXT;
- Typ : Printer_Type;
- Code : EAN_13;
- NLines : INTEGER);
-
-
- IMPLEMENTATION
-
-
- FUNCTION Num (Arg : INTEGER) : STRING;
- VAR
- St : STRING [20];
- BEGIN
- STR (Arg,St);
- Num := St;
- END;
-
-
- PROCEDURE Print_BarCode (VAR Lst : TEXT; Typ : Printer_Type;
- Code : EAN_13; NLines : INTEGER);
-
- CONST
- Max_Code_Len = 2*3 + 5 + 7*12; { For 12 digit bar code }
-
- ESC = #27;
-
-
- TYPE
- Bar_Position = (Left,Centre,Right);
- One_Dig = STRING [7];
- Buffer = ARRAY [1..1024] OF CHAR;
-
-
- VAR
- LCode : EAN_13; { Local Copy, padded & checked }
- Seg_Size, { Left/Right Segment Size }
- Code_Len, { Size of BarCode in digits }
- Bar_Len, { Size of Barcode in bar units }
- Bytes, { Bytes per bar unit }
- Line_Len, { Line Length in Gfx Mode }
- Mult : INTEGER; { Number of Lines per char line}
-
- Full_Code : STRING [Max_Code_Len];
-
- PBuffer : ^Buffer;
- Posn : INTEGER; { Buffer Position }
-
-
- PROCEDURE Rationalise_Code;
- VAR
- I : INTEGER;
- BEGIN
- IF LENGTH (Code) > 8
- THEN Seg_Size := 6
- ELSE Seg_Size := 4;
-
- Code_Len := Seg_Size * 2;
-
- LCode := Code;
- FOR I := LENGTH(LCode)+1 TO Code_Len-1 { Pad with Leading Zeros }
- DO LCode := '0' + LCode;
-
- Bar_Len := 2*3 + 5 + 7*Code_Len;
- { LRG CG CODE }
- END;
-
-
- PROCEDURE Calc_Check_Digit;
- VAR
- I, C1 : INTEGER;
- BEGIN
- IF Code_Len <> LENGTH(LCode)+1 { If already there, assume ok }
- THEN EXIT;
-
- C1 := 0;
- FOR I := Seg_Size DOWNTO 1
- DO INC (C1,ORD(LCode[I*2-1])-$30);
- C1 := C1 * 3;
- FOR I := Seg_Size-1 DOWNTO 1
- DO INC (C1,ORD(LCode[I*2])-$30);
-
- LCode := LCode + CHR (((10-(C1 MOD 10)) MOD 10) +$30);
- END;
-
-
- PROCEDURE Guard (Which : Bar_Position);
- VAR
- Dig : One_Dig;
- BEGIN
- CASE Which OF
- Centre : Dig := '01010';
- ELSE Dig := '101';
- END;
- Full_Code := Full_Code + Dig;
- END;
-
-
- FUNCTION DigA (Arg : EAN_13) : One_Dig;
- VAR
- Dig : One_Dig;
- I : INTEGER;
- BEGIN
- FOR I := 1 TO LENGTH (Arg)
- DO BEGIN
- CASE Arg[I] OF
- '9' : Dig := '0001011';
- '8' : Dig := '0110111';
- '7' : Dig := '0111011';
- '6' : Dig := '0101111';
- '5' : Dig := '0110001';
- '4' : Dig := '0100011';
- '3' : Dig := '0111101';
- '2' : Dig := '0010011';
- '1' : Dig := '0011001';
- ELSE Dig := '0001101';
- END;
- Full_Code := Full_Code + Dig;
- END;
- END;
-
-
- PROCEDURE DigB (Arg : EAN_13);
- VAR
- Dig : One_Dig;
- I : INTEGER;
- BEGIN
- FOR I := 1 TO LENGTH (Arg)
- DO BEGIN
- CASE Arg[I] OF
- '9' : Dig := '0010111';
- '8' : Dig := '0001001';
- '7' : Dig := '0010001';
- '6' : Dig := '0111001';
- '5' : Dig := '0111001';
- '4' : Dig := '0011101';
- '3' : Dig := '0100001';
- '2' : Dig := '0011011';
- '1' : Dig := '0110011';
- ELSE Dig := '0100111';
- END;
- Full_Code := Full_Code + Dig;
- END;
- END;
-
-
- PROCEDURE DigC (Arg : EAN_13);
- VAR
- Dig : One_Dig;
- I : INTEGER;
- BEGIN
- FOR I := 1 TO LENGTH (Arg)
- DO BEGIN
- CASE Arg[I] OF
- '9' : Dig := '1110100';
- '8' : Dig := '1001000';
- '7' : Dig := '1000100';
- '6' : Dig := '1010000';
- '5' : Dig := '1001110';
- '4' : Dig := '1011100';
- '3' : Dig := '1000010';
- '2' : Dig := '1101100';
- '1' : Dig := '1100110';
- ELSE Dig := '1110010';
- END;
- Full_Code := Full_Code + Dig;
- END;
- END;
-
-
- PROCEDURE Compose_Code;
- BEGIN
- Full_Code := '';
- Guard (Left);
- DigA (COPY(LCode,1,Seg_Size));
- Guard (Centre);
- DigC (COPY(LCode,Seg_Size+1,Seg_Size*2));
- Guard (Right);
- END;
-
-
- PROCEDURE Init_Buffer;
- BEGIN
- NEW (PBuffer);
- FILLCHAR (PBUffer^,SIZEOF(PBuffer^),#0);
- Posn := 0;
-
- CASE Typ OF
- Epson : BEGIN
- Bytes := 3*3; { 3 pixels x 24 pins }
- Line_Len := 3*Bar_Len;
- Mult := 1;
- END;
- Ibm : BEGIN
- Bytes := 4; { 4 pixels X 8 pins }
- Line_Len := 4*Bar_Len;
- Mult := 1;
- END;
- ELSE BEGIN
- Bytes := 0; { 5 pixels }
- Line_Len := (5*Bar_Len +7) DIV 8;
- Mult := 37 * NLines;
- NLines := 1;
- END;
- END;
- END;
-
-
- PROCEDURE Send_Preamble;
- VAR
- St : STRING [20];
- BEGIN
- IF NLines <> 1
- THEN BEGIN
- CASE Typ OF
- Epson : St := ESC+'0';
- Ibm : St := ESC+'3'#24;
- ELSE St := ESC+'&l8D';
- END;
- WRITE (Lst,St);
- END;
- END;
-
-
- PROCEDURE Send_Postamble;
- BEGIN
- IF NLines <> 1
- THEN IF Typ = Laser
- THEN WRITE (Lst,ESC,'&l6D')
- ELSE WRITE (Lst,ESC,'2');
- END;
-
-
- PROCEDURE Send_Buffer;
- VAR
- I : INTEGER;
- BEGIN
- CASE Typ OF
- Epson : WRITE (Lst,ESC,'*'#$27,CHR(Line_Len MOD 256),CHR(Line_Len DIV 256));
- Ibm : WRITE (Lst,ESC,'Z',CHR(Line_Len MOD 256),CHR(Line_Len DIV 256));
- ELSE WRITE (Lst,ESC,'*t300R',ESC,'*r1A',ESC,'*b',Line_Len,'W');
- END;
-
- FOR I := 1 TO Posn
- DO WRITE (Lst,PBuffer^[I]);
-
- CASE Typ OF
- Laser : WRITE (Lst, ESC, '*rB');
- END;
- END;
-
-
- PROCEDURE Compose_Buffer;
- VAR
- I : INTEGER;
- Bar : CHAR;
- Blk,
- Spc : STRING [12];
-
- PROCEDURE Add (St : STRING);
- BEGIN
- MOVE (St[1],PBuffer^[Posn+1],LENGTH (St));
- INC (Posn,LENGTH (St));
- END;
-
- VAR
- Frag, Len : INTEGER;
-
- PROCEDURE Add_Frag (B : BYTE);
- BEGIN
- Frag := (Frag SHL 5) OR (B AND $1F);
- INC (Len,5);
- IF Len >= 8
- THEN BEGIN
- Add (CHR (Frag SHR (Len-8)));
- DEC (Len,8);
- END;
- END;
-
- PROCEDURE Add_Bar (Bar : CHAR);
- BEGIN
- IF Typ = Laser { 1-dot-line at a time }
- THEN BEGIN
- IF Bar = '0'
- THEN Add_Frag (0)
- ELSE Add_Frag ($1F);
- END
- ELSE BEGIN { 8/24-dot-lines at a time }
- IF Bar = '0'
- THEN Add (Spc)
- ELSE Add (Blk);
- END;
- END;
-
- BEGIN
- Frag := 0;
- Len := 0;
-
- Blk := ''; { Compose the unit stripes }
- Spc := '';
- FOR I := 1 TO Bytes
- DO BEGIN
- Blk := Blk + #$FF;
- Spc := Spc + #$00;
- END;
-
- FOR I := 1 TO LENGTH (Full_Code) { Compose Bars }
- DO Add_Bar (Full_Code [I]);
-
- IF Typ = Laser
- THEN WHILE Posn < Line_Len
- DO Add_Bar ('0')
- END;
-
-
- VAR
- I,J : INTEGER;
-
- BEGIN
-
- Rationalise_Code;
- Calc_Check_Digit;
- Compose_Code;
- Init_Buffer;
- Compose_Buffer;
-
- Send_Preamble;
-
- FOR I := 1 TO NLines
- DO BEGIN
- WRITE (Lst,'':PrnPosn);
- FOR J := 1 TO Mult
- DO BEGIN
- Send_Buffer;
- END;
- WRITELN (Lst);
- END;
-
- Send_Postamble;
- WRITELN (Lst,'':PrnPosn+2,LCode); WRITELN (Lst);
- END;
-
-
- END.
-
- { ---------------------- TEST PROGRAM ---------------------------------- }
-
- USES
- Crt, Barcode, Printer;
-
-
- VAR
- { Lst : TEXT;}
- Ch : CHAR;
- Typ : Printer_Type;
-
- BEGIN
- WRITELN;
- WRITELN ('Bar Code Test');
- WRITELN;
-
- WRITE ('Select Printer Type (E=Epson, I=IbmPro, L=HPLaser) ');
-
- Ch := UPCASE (READKEY);
-
- CASE Ch OF
- 'L' : Typ := Laser;
- 'I' : Typ := Ibm;
- 'E' : Typ := Epson;
- ELSE EXIT;
- END;
-
- { ASSIGN (Lst,'TEST');
- REWRITE (Lst);}
-
- Print_BarCode (Lst,Typ,'1234567', 1);
- Print_BarCode (Lst,Typ, '9876543', 1);
- Print_BarCode (Lst,Typ,'12345678901',1);
-
- Print_BarCode (Lst,Typ,'1234567', 2);
- Print_BarCode (Lst,Typ, '9876543', 2);
- Print_BarCode (Lst,Typ,'12345678901',2);
-
- WRITE (Lst,#$0C);
-
- { CLOSE (Lst);}
- END.
-